#include <iostream>
#include "MYDecode.h"
#include "AudioPlay.h"
#include "MYResample.h"
#include "MYAudioThread.h"

using namespace std;

MYAudioThread::MYAudioThread()
{
    if(!res) res = new MYResample();
    if(!ap) ap = AudioPlay::Get();
}

MYAudioThread::~MYAudioThread()
{
    // 等待线程退出
    isExit = true;
    wait();
}

bool MYAudioThread::Open(AVCodecParameters *para, int sampleRate, int channels)
{
    if(!para) return false;
    Clear();

    mux.lock();
    pts = 0;
    bool ret = true;
    // 打开重采样器
    if(!res->Open(para, false)) {
        cout << "MYResample open failed!" << endl;
        ret = false;
    }
    // 设置播放采样率和通道
    ap->sampleRate = sampleRate;
    ap->channels = channels;
    // 打开音频播放器
    if(!ap->Open()) {
        cout << "AudioPlay open failed!" << endl;
        ret = false;
    }
    // 打开解码器
    if(!decode->Open(para)) {
        cout << "Audio MYDecode open failed!" << endl;
        ret = false;
    }
    mux.unlock();
    cout << "MYAudioThread::Open success! : " << ret << endl;
    return ret;
}

void MYAudioThread::Close()
{
    // 关闭解码线程
    MYDecodeThread::Close();
    if(res) {
        res->Close();
        amux.lock();
        delete res;
        res = NULL;
        amux.unlock();
    }
    if(ap) {
        ap->Close();
        amux.lock();
        ap = NULL;
        amux.unlock();
    }
}

void MYAudioThread::Clear()
{
    // 清理解码任务队列
    MYDecodeThread::Clear();
    mux.lock();
    if(ap) ap->Clear();
    mux.unlock();
}

void MYAudioThread::run()
{
    unsigned char *pcm = new unsigned char[8 * 1024 * 1024 * 10];
    while(!isExit) {
        amux.lock();
        if(isPause) {
            amux.unlock();
            msleep(5);
            continue;
        }
        // 从队列取出一个packet数据来解码
        AVPacket *pkt = Pop();
        // 发送给解码器解码
        bool ret = decode->Send(pkt);

        if(!ret) {
            amux.unlock();
            msleep(1);
            continue;
        }

        // 一次send 可能需要多次recv才能处理完
        while(!isExit) {
            AVFrame *frame = decode->Recv();
            if(!frame) break;

            // 减去缓冲中未播放时间
            pts = decode->pts - ap->GetNoPlayMs();

            // 重采样，确保不失真
            int size = res->Resample(frame, pcm);
            // 播放音频
            while(!isExit) {
                if(size <= 0) break;
                // 缓冲未播放完，空间不够
                if(ap->GetFree() < size || isPause) {
                    msleep(1);
                    continue;
                }
                // 把当前解码得到的数据传入io设备播放
                ap->Write(pcm, size);
                break;
            }
        }
        amux.unlock();

    }
    delete []pcm;
}

void MYAudioThread::SetPause(bool isPause)
{
    this->isPause = isPause;
    if(ap) {
        ap->SetPause(isPause);
    }
}

void MYAudioThread::SetVolume(double newVolume)
{
    if(!ap) return;
    ap->SetVolume(newVolume);
}
